using System;
using System.Collections;
using System.Diagnostics;
using System.Threading;
using Rhizome.Internal;

namespace Rhizome.Model
{
    public partial class ActiveObjectHost
    {
        #region Nested type: ActiveObjectHostSynchronizationContext

        private sealed class ActiveObjectHostSynchronizationContext : SynchronizationContext
        {
            private readonly ActiveObjectHost _host;

            public ActiveObjectHostSynchronizationContext(ActiveObjectHost activeObjectHost)
            {
                if (activeObjectHost == null) throw new ArgumentNullException("activeObjectHost");
                _host = activeObjectHost;
            }

            private bool CheckAccess
            {
                [DebuggerStepThrough]
                get { return _host._activator.CheckAccess; }
            }

            private static IEnumerator Coroutine(SendOrPostCallback d, object state)
            {
                d(state);
                yield break;
            }

            public override void Send(SendOrPostCallback d, object state)
            {
                if (CheckAccess)
                {
                    d(state);
                    return;
                }

                var activeObject = new DelegateActiveObject(_host, Coroutine(d, state));
                lock (activeObject.StopMonitor)
                {
                    activeObject.Active = true;
                    Monitor.Wait(activeObject.StopMonitor);
                }
            }

            public override void Post(SendOrPostCallback d, object state)
            {
                if (CheckAccess) // todo: check it
                {
                    d(state);
                    return;
                }

                new DelegateActiveObject(_host, Coroutine(d, state)) {Active = true};
            }

            public override SynchronizationContext CreateCopy()
            {
                return new ActiveObjectHostSynchronizationContext(_host);
            }
        }

        #endregion
    }
}